@@ -57,17 +57,8 @@ class Service < ActiveRecord::Base |
||
| 57 | 57 |
(config = Devise.omniauth_configs[provider.to_sym]) && config.args[1] |
| 58 | 58 |
end |
| 59 | 59 |
|
| 60 |
- def self.provider_specific_options(omniauth) |
|
| 61 |
- case omniauth['provider'].to_sym |
|
| 62 |
- when :'37signals' |
|
| 63 |
- { user_id: omniauth['extra']['accounts'][0]['id'], name: omniauth['info']['name'] }
|
|
| 64 |
- else |
|
| 65 |
- { name: omniauth['info']['nickname'] || omniauth['info']['name'] }
|
|
| 66 |
- end |
|
| 67 |
- end |
|
| 68 |
- |
|
| 69 | 60 |
def self.initialize_or_update_via_omniauth(omniauth) |
| 70 |
- options = provider_specific_options(omniauth) |
|
| 61 |
+ options = get_options(omniauth) |
|
| 71 | 62 |
|
| 72 | 63 |
find_or_initialize_by(provider: omniauth['provider'], uid: omniauth['uid'].to_s).tap do |service| |
| 73 | 64 |
service.assign_attributes token: omniauth['credentials']['token'], |
@@ -78,4 +69,24 @@ class Service < ActiveRecord::Base |
||
| 78 | 69 |
options: options |
| 79 | 70 |
end |
| 80 | 71 |
end |
| 72 |
+ |
|
| 73 |
+ def self.register_options_provider(provider_name, &block) |
|
| 74 |
+ option_providers[provider_name] = block |
|
| 75 |
+ end |
|
| 76 |
+ |
|
| 77 |
+ def self.get_options(omniauth) |
|
| 78 |
+ option_providers.fetch(omniauth['provider'], option_providers['default']).call(omniauth) |
|
| 79 |
+ end |
|
| 80 |
+ |
|
| 81 |
+ private |
|
| 82 |
+ @@option_providers = HashWithIndifferentAccess.new |
|
| 83 |
+ cattr_reader :option_providers |
|
| 84 |
+ |
|
| 85 |
+ register_options_provider('default') do |omniauth|
|
|
| 86 |
+ {name: omniauth['info']['nickname'] || omniauth['info']['name']}
|
|
| 87 |
+ end |
|
| 88 |
+ |
|
| 89 |
+ register_options_provider('37signals') do |omniauth|
|
|
| 90 |
+ {user_id: omniauth['extra']['accounts'][0]['id'], name: omniauth['info']['name']}
|
|
| 91 |
+ end |
|
| 81 | 92 |
end |
@@ -5,22 +5,23 @@ describe OmniauthCallbacksController do |
||
| 5 | 5 |
sign_in users(:bob) |
| 6 | 6 |
OmniAuth.config.test_mode = true |
| 7 | 7 |
request.env["devise.mapping"] = Devise.mappings[:user] |
| 8 |
- request.env["omniauth.auth"] = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/twitter.json')))
|
|
| 9 | 8 |
end |
| 10 | 9 |
|
| 11 | 10 |
describe "accepting a callback url" do |
| 12 | 11 |
it "should update the user's credentials" do |
| 12 |
+ request.env["omniauth.auth"] = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/twitter.json')))
|
|
| 13 | 13 |
expect {
|
| 14 | 14 |
get :twitter |
| 15 | 15 |
}.to change { users(:bob).services.count }.by(1)
|
| 16 | 16 |
end |
| 17 |
+ end |
|
| 17 | 18 |
|
| 18 |
- # it "should work with an unknown provider (for now)" do |
|
| 19 |
- # request.env["omniauth.auth"]['provider'] = 'unknown' |
|
| 20 |
- # expect {
|
|
| 21 |
- # get :unknown |
|
| 22 |
- # }.to change { users(:bob).services.count }.by(1)
|
|
| 23 |
- # expect(users(:bob).services.first.provider).to eq('unknown')
|
|
| 24 |
- # end |
|
| 19 |
+ describe "handling a provider with non-standard omniauth options" do |
|
| 20 |
+ it "should update the user's credentials" do |
|
| 21 |
+ request.env["omniauth.auth"] = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/37signals.json')))
|
|
| 22 |
+ expect {
|
|
| 23 |
+ get "37signals" |
|
| 24 |
+ }.to change { users(:bob).services.count }.by(1)
|
|
| 25 |
+ end |
|
| 25 | 26 |
end |
| 26 | 27 |
end |
@@ -98,6 +98,7 @@ describe Service do |
||
| 98 | 98 |
expect(service.token).to eq('a1b2c3d4...')
|
| 99 | 99 |
expect(service.secret).to eq('abcdef1234')
|
| 100 | 100 |
end |
| 101 |
+ |
|
| 101 | 102 |
it "should work with 37signals services" do |
| 102 | 103 |
signals = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/37signals.json')))
|
| 103 | 104 |
expect {
|
@@ -113,6 +114,7 @@ describe Service do |
||
| 113 | 114 |
expect(service.options[:user_id]).to eq(12345) |
| 114 | 115 |
service.expires_at = Time.at(1401554352) |
| 115 | 116 |
end |
| 117 |
+ |
|
| 116 | 118 |
it "should work with github services" do |
| 117 | 119 |
signals = JSON.parse(File.read(Rails.root.join('spec/data_fixtures/services/github.json')))
|
| 118 | 120 |
expect {
|
@@ -126,4 +128,27 @@ describe Service do |
||
| 126 | 128 |
expect(service.token).to eq('agithubtoken')
|
| 127 | 129 |
end |
| 128 | 130 |
end |
| 131 |
+ |
|
| 132 |
+ describe 'omniauth options provider registry for non-conforming omniauth responses' do |
|
| 133 |
+ describe '.register_options_provider' do |
|
| 134 |
+ before do |
|
| 135 |
+ Service.register_options_provider('test-omniauth-provider') do |omniauth|
|
|
| 136 |
+ { name: omniauth['special_field'] }
|
|
| 137 |
+ end |
|
| 138 |
+ end |
|
| 139 |
+ |
|
| 140 |
+ after do |
|
| 141 |
+ Service.option_providers.delete('test-omniauth-provider')
|
|
| 142 |
+ end |
|
| 143 |
+ |
|
| 144 |
+ it 'allows gem developers to add their own options provider to the registry' do |
|
| 145 |
+ actual_options = Service.get_options({
|
|
| 146 |
+ 'provider' => 'test-omniauth-provider', |
|
| 147 |
+ 'special_field' => 'A Great Name' |
|
| 148 |
+ }) |
|
| 149 |
+ |
|
| 150 |
+ expect(actual_options[:name]).to eq('A Great Name')
|
|
| 151 |
+ end |
|
| 152 |
+ end |
|
| 153 |
+ end |
|
| 129 | 154 |
end |